package com.pro.common.service.file.service.unit;

import cn.hutool.core.collection.CollUtil;
import com.pro.common.api.user.file.enums.EnumFileNodeType;
import com.pro.common.api.user.file.enums.EnumFileStatus;
import com.pro.common.api.user.file.model.db.UserFile;
import com.pro.common.api.user.file.model.db.UserFileNode;
import com.pro.common.service.file.service.UserFileNodeService;
import com.pro.common.service.file.service.UserFileService;
//import com.pro.common.service.file.service.UserFolderService;
import com.pro.common.service.file.util.PathTemplateUtil;
import com.pro.common.service.file.util.sub.UserFilePathParam;
import com.pro.common.service.file.util.sub.UserFilePathResult;
import com.pro.common.service.model.mapstruct.UserModelMapper;
import com.pro.framework.api.util.CollUtils;
import com.pro.framework.api.util.StrUtils;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

/**
 * 文件聚合服务
 */
@Service
@AllArgsConstructor
public class UserFileUnitService {
    private UserFileService userFileService;
//    private UserFolderService userFolderService;
    private UserFileNodeService userFileNodeService;
    private UserModelMapper userModelMapper;

    // 列出所有文件和目录
    public UserFile listFileAndFolder(UserFile userFile) {
        return userFileService.getOne(userFile);
    }

    @Transactional(rollbackFor = Exception.class)
    public void saveBatchFull(List<UserFileNode> list) {
        if (CollUtil.isEmpty(list)) return;

        // 1. 处理父目录，返回逻辑路径到 UserFileNode 映射，以及需要新增的目录
        Map<String, UserFileNode> existMap = new HashMap<>();
        List<UserFileNode> toInsertParents = new ArrayList<>();
        processParentDirectories(list, existMap, toInsertParents);

        // 2. 统一保存父目录（如果有新增）
        if (CollUtil.isNotEmpty(toInsertParents)) {
            userFileNodeService.saveBatch(toInsertParents);
            toInsertParents.forEach(p -> existMap.put(p.getLogicalPath(), p));
        }

        // 3. 回填每个文件节点的 parentId
        list.forEach(f -> {
            List<UserFileNode> parentList = f.getParentList();
            if (CollUtil.isNotEmpty(parentList)) {
                String parentPath = parentList.get(parentList.size() - 1).getLogicalPath();
                UserFileNode parent = existMap.get(parentPath);
                f.setParentId(parent != null ? parent.getId() : 0L);
            } else {
                f.setParentId(0L);
            }
        });

        // 4. 保存文件节点
        userFileNodeService.saveBatch(list);

        // 5. 回填文件节点ID到 UserFile
        list.forEach(f -> f.getUserFile().setFileNodeId(f.getId()));

        // 6. 保存文件
        userFileService.saveBatch(list.stream().map(UserFileNode::getUserFile).toList());
    }

    /**
     * 收集父目录，不做保存
     */
    private void processParentDirectories(List<UserFileNode> nodes,
                                          Map<String, UserFileNode> existMap,
                                          List<UserFileNode> toInsertParents) {
        if (CollUtil.isEmpty(nodes)) return;

        Map<Long, List<UserFileNode>> groupByUser = nodes.stream()
                .collect(Collectors.groupingBy(UserFileNode::getUserId));

        for (Map.Entry<Long, List<UserFileNode>> entry : groupByUser.entrySet()) {
            Long userId = entry.getKey();
            List<UserFileNode> userFiles = entry.getValue();

            // 收集所有父目录，去重
            List<UserFileNode> allParents = userFiles.stream()
                    .flatMap(f -> f.getParentList().stream())
                    .filter(p -> p.getId() == null)
                    .filter(p -> p.getType() == EnumFileNodeType.FOLDER) // 只保留目录 type = 1
                    .collect(Collectors.collectingAndThen(
                            Collectors.toMap(UserFileNode::getLogicalPath, Function.identity(), (a, b) -> a),
                            m -> new ArrayList<>(m.values())
                    ));


            if (CollUtil.isEmpty(allParents)) continue;

            // 查询已存在的目录
            List<String> allPaths = allParents.stream().map(UserFileNode::getLogicalPath).toList();
            Map<String, UserFileNode> dbExistMap = userFileNodeService.listByUserAndPaths(userId, allPaths)
                    .stream().collect(Collectors.toMap(UserFileNode::getLogicalPath, Function.identity()));

            // 标记需要新增的目录
            allParents.forEach(p -> {
                if (!dbExistMap.containsKey(p.getLogicalPath()) && !existMap.containsKey(p.getLogicalPath())) {
                    toInsertParents.add(p);
                } else {
                    existMap.put(p.getLogicalPath(), dbExistMap.getOrDefault(p.getLogicalPath(), p));
                }
            });
        }
    }


    public UserFileNode buildFull(UserFilePathParam req, String bucketName) {

        Long userId = req.getUserId();
        String batchId = req.getBatchId();
        Long createBy = req.getCreateBy();

        // 1. 解析路径
        UserFilePathResult result = PathTemplateUtil.buildPath(req);
        String logicalPath = result.getLogicalPath();       // /documents/work/
        String ancestorPath = result.getAncestorPath();     // /root/1/23/
        String nodeName = result.getNodeName();             // 当前节点名
        String physicalPath = result.getPhysicalPath();

        UserFileNode fileNode = new UserFileNode();

        // 2. 查找/构建父级文件夹链路
        StringBuilder currentPath = new StringBuilder();
        String[] parts = logicalPath.split("/");
        // 注意 -1，排除最后一个文件名
        fileNode.setParentList(Arrays.stream(parts, 0, parts.length - 1)
                .filter(StrUtils::isNotBlank)
                .map(part -> {
                    currentPath.append("/").append(part);
                    UserFileNode folderNode = new UserFileNode();
                    folderNode.setUserId(userId);
                    folderNode.setNodeName(part);
                    folderNode.setParentId(0L); // 占位
                    folderNode.setLogicalPath(currentPath + "/");
                    folderNode.setAncestorPath(ancestorPath);
                    folderNode.setType(EnumFileNodeType.FOLDER);
                    folderNode.setCreatedBy(createBy);
                    return folderNode;
                })
                .collect(Collectors.toList()));

        // 3. 构建最终的文件节点
        fileNode.setUserId(userId);
        fileNode.setNodeName(nodeName);
//        fileNode.setParentId(null);
        fileNode.setLogicalPath(logicalPath);
        fileNode.setAncestorPath(ancestorPath);
        fileNode.setRecycleBatchId(StrUtils.isBlank(batchId) ? null : Long.valueOf(batchId));
        fileNode.setCreatedBy(createBy);
//        fileNode.setFeatureTag(template);
        fileNode.setType(EnumFileNodeType.FILE);
        fileNode.setExtension(result.getExtension());
        fileNode.setContentType(result.getContentType());
        fileNode.setSizeBytes(result.getSizeBytes());

//        fileNode.setUrl(url);

        // 4. 构建文件信息
        UserFile userFile = new UserFile();
        userFile.setUserId(userId);
        userFile.setFileNodeId(fileNode.getId()); // 注意：这里要在保存后拿到 id 再设置
        userFile.setStorageKey(physicalPath);
        userFile.setBucket(bucketName);
        userFile.setStatus(EnumFileStatus.NORMAL);
        fileNode.setUserFile(userFile);

        // 5. 文件夹关联
//        fileNode.setUserFolders(createdFolders);

        return fileNode;
    }


}
